package controller

import (
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/gogf/gf/errors/gerror"
	"gitlab.local/DO-module/new-filemanage-module/src/controller/errcode"
	"gitlab.local/TerraMaster/tos-modules/core/tosutils"

	//"gitlab.local/DO-module/new-filemanage-module/src/core/fileoperate"
	"gitlab.local/DO-module/new-filemanage-module/src/core/middleware"
	"gitlab.local/DO-module/new-filemanage-module/src/service/filesystem"
	"gitlab.local/DO-module/new-filemanage-module/src/service/folder"
	flog "gitlab.local/DO-module/new-filemanage-module/src/service/log"
	acl2 "gitlab.local/TerraMaster/tos-modules/core/acl"
	fileoperate2 "gitlab.local/TerraMaster/tos-modules/fileoperate"

	//"gitlab.local/TerraMaster/tos-modules/middleware"
	"gitlab.local/golibrary/resp"
	"net/http"
	"strconv"
)

type FileShowController struct {
	fSys       *filesystem.FileSystem
	aclGetter  acl2.FolderAttrService
	folders    *folder.Folder
	fOptGetter fileoperate2.Getter
}

func InitFileShowRouter(engine *gin.Engine,
	checker middleware.AuthChecker,
	fOptGetter fileoperate2.Getter,
	aclGetter acl2.FolderAttrService,
	fSys *filesystem.FileSystem,
	folders *folder.Folder) *FileShowController {
	fs := FileShowController{}
	fs.fSys = fSys
	fs.aclGetter = aclGetter
	fs.folders = folders
	fs.fOptGetter = fOptGetter

	fileManage := engine.Group("/fileManage", checker.LoginAuthed())
	{
		fileManage.GET("/multimediaPlay", fs.handleMultimediaPlay)                             //多媒体播放
		fileManage.Any("/getThumbnail", fs.handleGetThumbnail)                                 //获取缩略图
		fileManage.GET("/homeList", resp.WrapResp(fs.handleHomeList))                          //获取侧边栏列表
		fileManage.GET("/USBList", resp.WrapResp(fs.handleUSBList))                            //获取侧边栏列表
		fileManage.GET("/folderInfo", resp.WrapResp(fs.handleFolder))                          //获取当前目录下文件及文件夹信息
		fileManage.GET("/folderInfoAll", resp.WrapResp(fs.handleFolderAll))                    //获取文件详细信息
		fileManage.GET("/getPathSize", resp.WrapResp(fs.handleGetPathSize))                    //获取目录剩余可用容量
		fileManage.GET("/getUserOrGroup", resp.WrapResp(fs.handleGetUserOrGroup))              //获取所有用户组及用户名称
		fileManage.POST("/modifyUsersAndGroups", resp.WrapResp(fs.handleModifyUsersAndGroups)) //修改文件用户和用户组acl权限信息(异步)
		fileManage.GET("/GetByPathTaskResult", resp.WrapResp(fs.handleGetByPathTaskResult))    //获取acl修改任务结果
		fileManage.GET("/isAdmin", resp.WrapResp(fs.handleIsAdmin))                            //是否是管理员组成员
		fileManage.GET("/isRootAdmin", resp.WrapResp(fs.handleIsRootAdmin))                    //是否是超级管理员用户
		fileManage.GET("/FileStatus", resp.WrapResp(fs.handleFileStatus))                      //文件状态(分享，收藏，最近)
		fileManage.GET("/GetFolderSize", resp.WrapResp(fs.handleGetFolderSize))                //异步获取文件或文件夹占用大小
		fileManage.GET("/GetDirTree", resp.WrapResp(fs.handleGetDirTree))                      //获取文件管理左侧目录树
		fileManage.POST("/SetFolderAssignAcl", resp.WrapResp(fs.handleSetFolderAssignAcl))     //设置文件夹为指定权限，全部用户统一权限
		fileManage.GET("/FolderEmpty", resp.WrapResp(fs.handleFolderEmpty))                    //文件夹是否为空
	}

	return &fs
}

// handleHomeList 获取文件管理菜单列表文件夹
func (fs *FileShowController) handleHomeList(c *gin.Context) (interface{}, error) {
	username, err := middleware.GetUserName(c)
	if err != nil {
		return nil, err
	}
	return fs.folders.GetHomeListFilter(username)
}

func (fs *FileShowController) handleUSBList(c *gin.Context) (interface{}, error) {
	username, err := middleware.GetUserName(c)
	if err != nil {
		return nil, err
	}
	return fs.folders.GetUSBListFilter(username)
}

// handleFolder 获取路径下文件及文件夹信息
func (fs *FileShowController) handleFolder(c *gin.Context) (interface{}, error) {
	//路径
	path := c.Query("path")
	if path == "" {
		return nil, fmt.Errorf("path is empty[%s]", path)
	}
	username, err := middleware.GetUserName(c)
	if err != nil {
		return nil, err
	}
	//判断读权限
	if !fs.aclGetter.IsRead(path, username) {
		return nil, gerror.NewCode(errcode.PermissionDenied, path)
	}
	page, _ := strconv.Atoi(c.Query("page"))
	limit, _ := strconv.Atoi(c.Query("limit"))
	depth, _ := strconv.Atoi(c.Query("depth"))

	return fs.folders.GetFoldersFilter(path, username, limit, page, fileoperate2.OrderRule(c.Query("rule")), c.Query("order") == "true", depth, c.Request.Context())
}

// handleFolderAll 获取文件详细信息
func (fs *FileShowController) handleFolderAll(c *gin.Context) (interface{}, error) {
	//路径
	path := c.Query("path")
	if path == "" {
		return nil, errors.New("request path error")
	}
	username, err := middleware.GetUserName(c)
	if err != nil {
		return nil, err
	}
	return fs.fOptGetter.GetFoldersFilter(path, username, c.Request.Context())
}

// handleGetPathSize 获取目录剩余可用容量
func (fs *FileShowController) handleGetPathSize(c *gin.Context) (interface{}, error) {
	path := c.Query("path")
	if path == "" {
		return 0, errors.New("the path is empty")
	}
	return fs.folders.GetPathSize(path)
}

// handleGetUserOrGroup 获取所有用户组及用户名称
func (fs *FileShowController) handleGetUserOrGroup(*gin.Context) (interface{}, error) {
	return fs.fSys.FileShow.HandleGetUserOrGroup()
}

// handleModifyUsersAndGroups 修改文件用户和用户组acl权限信息
func (fs *FileShowController) handleModifyUsersAndGroups(c *gin.Context) (interface{}, error) {
	uname, err := middleware.GetUserName(c)
	if err != nil {
		return nil, err
	}
	var data struct {
		Path    string       `json:"path"`    //文件路径
		Replace bool         `json:"replace"` //替换
		Acls    []acl2.Attrs `json:"acls"`    //文件用户acl
	}
	//解析json
	if e := c.ShouldBindJSON(&data); e != nil {
		flog.RecordedLog(flog.Err, uname, flog.HttpTag, "failed to modify file permissions procedure", c.ClientIP())
		return "", e
	}
	if data.Path == "" {
		flog.RecordedLog(flog.Err, uname, flog.HttpTag, "failed to modify file permissions procedure", c.ClientIP())
		return "", errors.New("path is empty")
	}
	taskId := fs.aclGetter.AddByPathTask(data.Path, data.Replace, data.Acls)
	flog.RecordedLog(flog.Info, uname, flog.HttpTag, "succeeded in modifying the file permission procedure", c.ClientIP())
	go tosutils.ReStartBaseService("")

	return strconv.FormatInt(taskId, 10), nil //注意前端精度丢失
}

// handleGetByPathTaskResult 获取acl修改任务结果
func (fs *FileShowController) handleGetByPathTaskResult(c *gin.Context) (interface{}, error) {
	taskId, err := strconv.ParseInt(c.Query("task_id"), 10, 64)
	if err != nil {
		return 0, err
	}
	return fs.aclGetter.GetByPathTaskResult(taskId)
}

// handleIsAdmin 是否是管理员组成员
func (fs *FileShowController) handleIsAdmin(c *gin.Context) (interface{}, error) {
	username, err := middleware.GetUserName(c)
	if err != nil {
		return nil, err
	}
	return fs.folders.IsAdmin(username)
}

// handleIsRootAdmin 是否是超级管理员用户
func (fs *FileShowController) handleIsRootAdmin(c *gin.Context) (interface{}, error) {
	username, err := middleware.GetUserName(c)
	if err != nil {
		return nil, err
	}
	return fs.folders.IsRootAdmin(username)
}

// handleFileStatus 文件状态(分享，收藏，最近)
func (fs *FileShowController) handleFileStatus(c *gin.Context) (interface{}, error) {
	username, err := middleware.GetUserName(c)
	if err != nil {
		return nil, err
	}
	return fs.fSys.FileStatus(username), nil
}

// handleGetFolderSize 异步获取文件或文件夹占用大小
func (fs *FileShowController) handleGetFolderSize(c *gin.Context) (interface{}, error) {
	var data struct {
		Status         uint8 `json:"status"`
		Capacity       int64 `json:"capacity"`
		FileQuantity   int   `json:"file_quantity"`   //文件夹下总文件数量
		FolderQuantity int   `json:"folder_quantity"` //文件夹下总文件夹数量
	}
	path := c.Query("path")
	if path == "" {
		return data, errors.New("path empty")
	}
	data.Status, data.Capacity, data.FileQuantity, data.FolderQuantity = fs.fOptGetter.GetFolderSize(path, c)
	return data, nil
}

// handleGetDirTree 获取文件管理左侧目录树
func (fs *FileShowController) handleGetDirTree(c *gin.Context) (interface{}, error) {
	path := c.Query("path")
	if path == "" {
		return nil, errors.New("path empty")
	}
	username, err := middleware.GetUserName(c)
	if err != nil {
		return nil, err
	}
	return fs.folders.GetDirTree(username, path, c.Request.Context())
}

// handleSetFolderAssignAcl 设置文件夹为指定权限，全部用户统一权限
func (fs *FileShowController) handleSetFolderAssignAcl(c *gin.Context) (interface{}, error) {
	var data struct {
		Path string `json:"path"`
		Type string `json:"type"`
	}
	if err := c.BindJSON(&data); err != nil {
		return false, err
	}
	if data.Path == "" || data.Type == "" {
		return false, errors.New("parameter error")
	}
	err := fs.aclGetter.SetFolderAssignAcl(data.Path, data.Type)
	return err == nil, err
}

// handleFolderEmpty 文件夹是否为空
func (fs *FileShowController) handleFolderEmpty(c *gin.Context) (interface{}, error) {
	path := c.Query("path")
	if path == "" {
		return false, errors.New("path empty")
	}
	return fs.fSys.FileShow.FolderEmpty(path)
}

// handleGetThumbnail 获取缩略图
func (fs *FileShowController) handleGetThumbnail(c *gin.Context) {
	path := c.Query("path")
	if path == "" {
		c.String(http.StatusInternalServerError, "parameter parsing failed")
		return
	}
	if err := fs.folders.GetThumbnail(path, c); err != nil {
		c.String(http.StatusInternalServerError, err.Error())
	}
}

// handleMultimediaPlay 多媒体播放
func (fs *FileShowController) handleMultimediaPlay(c *gin.Context) {
	path := c.Query("path")
	if path == "" {
		c.String(http.StatusBadRequest, "parameter parsing failed")
		return
	}
	username, err := middleware.GetUserName(c)
	if err != nil {
		c.String(http.StatusBadRequest, "failed to get username")
		return
	}
	if path == "" {
		c.String(http.StatusBadRequest, "failed to get username")
		return
	}
	if err := fs.folders.MultimediaPlay(username, path, c); err != nil {
		c.String(http.StatusInternalServerError, err.Error())
	}
}
